package com.homework;

import com.homework.conn.ZkConn;
import com.homework.service.UserService;
import org.I0Itec.zkclient.IZkChildListener;
import org.I0Itec.zkclient.ZkClient;

import java.util.*;

public class ClientBoostrap {

    private static Map<String, UserService> userServiceMap = new HashMap<>(16);

    private static List<String> children;

    public static void main(String[] args) throws InterruptedException {
        ZkClient zkClient = new ZkClient("127.0.0.1:2181");
        System.out.println("zk连接成功.");
        String rootPath = "/netty_rpc";
        if (!zkClient.exists(rootPath)){
            System.out.println("服务器根节点不存在");
            System.exit(500);
        }
        String hostName = "127.0.0.1",port;

        children = zkClient.getChildren(rootPath);

        System.out.println("children -> "+children);

        zkClient.subscribeChildChanges(rootPath, new IZkChildListener(){
            @Override
            public void handleChildChange(String parentPath, List<String> list) throws Exception {
                System.out.println("节点 "+parentPath+" 发生了变更,当前子节点为:"+list);
                for (String s : list) {
                    String[] split = s.split(":");
                    // 如果当前节点不存在于原有节点列表,说明是新增节点,创建连接
                    if (!userServiceMap.containsKey(split[1])){
                        RpcConsumer consumer = new RpcConsumer();
                        userServiceMap.put(split[1],(UserService)consumer.createProxy(UserService.class,split[1]));
                        System.out.println("新增节点"+s+"成功.");
                    }
                }

                for (String child : children) {
                    // 如果原有节点列表不在当前子节点了，说明原有节点已经下线，进行剔除处理
                    if (!list.contains(child)){
                        String[] split = child.split(":");
                        userServiceMap.remove(split[1]);
                        System.out.println("剔除节点"+child+"成功!");
                    }
                }
                children = list;
            }
        });

        for (String child : children) {
            String[] split = child.split(":");
            port = split[1];
            System.out.println("连接服务端"+hostName+":"+port+" 开始...");
            RpcConsumer consumer = new RpcConsumer();
            userServiceMap.put(port,(UserService)consumer.createProxy(UserService.class,port));
            System.out.println("连接服务端"+hostName+":"+port+" 结束 ...");
        }

        while (true) {
            //目标server
            String targetServer = "";
            long expend = 0;
            long currentTime = System.currentTimeMillis() / 1000;
            //每次读取服务端列表,拿到其最后一次被调用的时间,找到时间最短的调用
            for (String s : children) {
                Object o = ZkConn.getZkClient().readData(rootPath + "/" + s);
                System.out.println("from "+s+" data = "+o);
                if (null == o){
                    System.out.println("continue...");
                    continue;
                }
                if ("start".equalsIgnoreCase(o.toString())){
                    targetServer = s;
                    break;
                }
                long tempTime = currentTime - Long.parseLong(o.toString());
                System.out.println("tempTime : "+tempTime);
                // 覆盖初始值
                if (expend == 0L) {
                    expend = tempTime;
                    System.out.println("continue expend = tempTime ...");
                    continue;
                }
                // 如果此服务端
                if (tempTime < expend){
                    targetServer = s;
                    expend = tempTime;
                }
            }

            // 如果目标服务器还是空值,说明时间一致,随机选一台进行调用
            if ("".equalsIgnoreCase(targetServer)){
                Random random = new Random();
                int targetIndex = random.nextInt(children.size());
                System.out.println("随机值为:"+targetIndex);
                targetServer = children.get(targetIndex);
            }
            System.out.println("children = "+children);
            System.out.println("targetServer = "+targetServer);
            // 第一题,客户端与每一个服务端都建立连接
//            System.out.println(userServiceMap.keySet());
//            for (String s : userServiceMap.keySet()) {
//                System.out.println(s);
//                System.out.println("get server return = " + userServiceMap.get(s).sayHello("ok?"));
//            }
            // 第二题,选择上面找出的目标服务端进行连接
            String[] split = targetServer.split(":");
            System.out.println("get server "+targetServer+" return = "+userServiceMap.get(split[1]).sayHello("ok?"));
            Thread.sleep(2000);
        }
    }
}
